package model

import (
	"context"

	"github.com/LyricTian/gin-admin/v7/internal/app/model/gormx/entity"
	"github.com/LyricTian/gin-admin/v7/internal/app/schema"
	"github.com/LyricTian/gin-admin/v7/pkg/errors"
	"github.com/google/wire"
	"github.com/jinzhu/gorm"
)

//var _ model.IGroupVideo = (*GroupVideo)(nil)

// GroupVideoSet 注入GroupVideo实例
var GroupVideoSet = wire.NewSet(wire.Struct(new(GroupVideo), "*"))

// GroupVideo 群视频存储
type GroupVideo struct {
	DB *gorm.DB
}

func (a *GroupVideo) getQueryOption(opts ...schema.GroupVideoQueryOptions) schema.GroupVideoQueryOptions {
	var opt schema.GroupVideoQueryOptions
	if len(opts) > 0 {
		return opts[0]
	}
	return opt
}

// Query 查询数据
func (a *GroupVideo) Query(ctx context.Context, params schema.GroupVideoQueryParam, opts ...schema.GroupVideoQueryOptions) (*schema.GroupVideoQueryResult, error) {
	db := entity.GetGroupVideoDB(ctx, a.DB)
	// TODO: 查询条件
	if v := params.GroupId; v != "" {
		db = db.Where("`group_id` = ?", v)
	}
	if v := params.ContentId; v != "" {
		db = db.Where("`content_id` = ?", v)
	}
	if v := params.Creator; v != "" {
		db = db.Where("`creator` = ?", v)
	}
	opt := a.getQueryOption(opts...)
	opt.OrderFields = append(opt.OrderFields, schema.NewOrderField("id", schema.OrderByDESC))
	db = db.Order(ParseOrder(opt.OrderFields))

	var list entity.GroupVideos
	pr, err := WrapPageQuery(ctx, db, params.PaginationParam, &list)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	qr := &schema.GroupVideoQueryResult{
		PageResult: pr,
		Data:       list.ToSchemaGroupVideos(),
	}

	return qr, nil
}

// GetFirst 查询第一条数据
func (a *GroupVideo) GetFirst(ctx context.Context, params schema.GroupVideoQueryParam, opts ...schema.GroupVideoQueryOptions) (*schema.GroupVideo, error) {
	db := entity.GetGroupVideoDB(ctx, a.DB)

	// TODO: 查询条件
	if v := params.GroupId; v != "" {
		db = db.Where("`group_id` = ?", v)
	}
	if v := params.ContentId; v != "" {
		db = db.Where("`content_id` = ?", v)
	}
	if v := params.Creator; v != "" {
		db = db.Where("`creator` = ?", v)
	}

	opt := a.getQueryOption(opts...)
	opt.OrderFields = append(opt.OrderFields, schema.NewOrderField("id", schema.OrderByDESC))
	db = db.Order(ParseOrder(opt.OrderFields))

	item := new(entity.GroupVideo)
	ok, err := FindOne(ctx, db, item)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	if !ok {
		return nil, nil
	}

	return item.ToSchemaGroupVideo(), nil
}

// Get 查询指定数据
func (a *GroupVideo) Get(ctx context.Context, id string, opts ...schema.GroupVideoQueryOptions) (*schema.GroupVideo, error) {
	db := entity.GetGroupVideoDB(ctx, a.DB).Where("id=?", id)
	var item entity.GroupVideo
	ok, err := FindOne(ctx, db, &item)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	if !ok {
		return nil, nil
	}

	return item.ToSchemaGroupVideo(), nil
}

// Create 创建数据
func (a *GroupVideo) Create(ctx context.Context, item schema.GroupVideo) error {
	eitem := entity.SchemaGroupVideo(item).ToGroupVideo()
	result := entity.GetGroupVideoDB(ctx, a.DB).Create(eitem)
	return errors.WithStack(result.Error)
}

// Update 更新数据
func (a *GroupVideo) Update(ctx context.Context, id string, item schema.GroupVideo) error {
	eitem := entity.SchemaGroupVideo(item).ToGroupVideo()
	result := entity.GetGroupVideoDB(ctx, a.DB).Where("id=?", id).Updates(eitem)

	return errors.WithStack(result.Error)
}

// Delete 删除数据
func (a *GroupVideo) Delete(ctx context.Context, id string) error {
	result := entity.GetGroupVideoDB(ctx, a.DB).Where("id=?", id).Delete(entity.GroupVideo{})

	return errors.WithStack(result.Error)
}

// sql
func (a *GroupVideo) SqlRows(ctx context.Context, sql string, value ...interface{}) (res []*schema.GroupVideo, err error) {
	//db := entity.GetGroupVideoDB(ctx, a.DB)
	db := a.DB

	rows, err := db.Raw(sql, value...).Rows()
	defer rows.Close()

	if err != nil {
		return nil, err
	}

	for rows.Next() {
		var s schema.GroupVideo
		if db.ScanRows(rows, &s) != nil {
			continue
		}
		// do something
		res = append(res, &s)
	}

	return
}

// sql
func (a *GroupVideo) SqlRow(ctx context.Context, sql string, value ...interface{}) (*schema.GroupVideo, error) {
	//db := entity.GetGroupVideoDB(ctx, a.DB)
	db := a.DB

	var res schema.GroupVideo

	errs := db.Raw(sql, value...).Scan(&res).GetErrors()
	if len(errs) > 0 {
		return nil, errs[0]
	}

	return &res, nil
}
func (a *GroupVideo) Exec(ctx context.Context, sql string, value ...interface{}) bool {
	//db := entity.GetGroupVideoDB(ctx, a.DB)
	db := a.DB

	errs := db.Exec(sql, value...).GetErrors()
	if len(errs) == 0 {
		return true
	}
	return false
}
